#ifndef __CLIENT_REQUEST_ANALYZER_H__
#define __CLIENT_REQUEST_ANALYZER_H__

// 因为在处理客户端发来的数据时，不能一股脑的读，还要边读边解析客户端的请求内容
/*解析规则要按不同的请求格式：GET、POST... 
    GET和POST请求首行格式都是：请求方法 + 空格 + 路径 + 协议版本
    剩余部分：关键字 + 冒号 + 空格 + 值
    每行都以\r\n结尾
    GET请求尾行是单独的空行，即\r\n（意味着每行数据的最短长度不小于2）
    POST格式和GET基本一致，与GET请求不同的是，POST最后一行的\r\n之后还有一行数据，该行数据长度由前面的Content-Length表示
GET请求格式如下：
首行\r\n
数据行1\r\n
...
数据行N\r\n
\r\n

POST请求：
首行\r\n
数据行1\r\n
...
数据行N\r\n
\r\n
其他数据
*/

#include <string>
#include <cstring>
#include <map>      // 类似于字典，适合表示键值对，并跟据键快速查找对应的值
#include <vector>   // 自适应可变长数组
#include "ClientSocketHandler.h"
#include "Defines.h"
#include <algorithm>// 可以使用std::transform()方法

// 该类用于解析客户端请求数据（在适度读取客户端数据后，对其进行解析）
class ClientRequestAnalyzer {
public:
    // 数据行（键值对）
    struct _RequestKeyData {
    public:
        std::string Key, Data;
    };

private:
    // 请求首行（请求方法名、路径、HTTP协议版本）
    std::string _requestName, _url, _httpVersion;
    // 请求数据行部分
    std::map<std::string, _RequestKeyData> _keyDataMap;
    // 标识是否解析成功
    bool _analyzeSuccessed;

public:
    ClientRequestAnalyzer(ClientSocketHandler *clientSocketHandler);
    // 把请求数据拆分成单独的行，存入动态数组lines
    void _requestToLines(ClientSocketHandler *clientSocketHandler, std::vector<std::string> &lines);
    // 解析首行数据
    void _analyzeFirstLine(std::string line);
    // 解析数据行（每行都是一个键值对）
    void _analyzeDataLine(std::string line);
    // 判断是否解析成功
    bool _isAnalyzeSuccessed();

public:
    // 获取请求方法名称
    std::string _getRequestName();
    // 获取请求路径
    std::string _getUrl();
    // 获取请求协议版本
    std::string _getHttpVersion();
    // 通过键获取数据行对应的值
    std::string _getDataByKey(std::string key);
};

#endif // !__CLIENT_REQUEST_ANALYZER_H__